package janino.resource;

import janino.compilador.IClass;
import janino.compilador.Descriptor;
import janino.compilador.IClassLoader;
import janino.compilador.ClassFileIClass;
import janino.compilador.Resource;
import janino.compilador.ClassFile;
import java.io.IOException;
import java.io.InputStream;

/**
 * This {@link org.codehaus.janino.IClassLoader} loads IClasses through a a {@link org.codehaus.janino.util.resource.ResourceFinder}
 * that designates
 * {@link org.codehaus.janino.util.ClassFile}s.
 */
public class ResourceFinderIClassLoader extends IClassLoader {

    private final ResourceFinder resourceFinder;

    public ResourceFinderIClassLoader(ResourceFinder resourceFinder, IClassLoader optionalParentIClassLoader) {
        super(optionalParentIClassLoader);
        this.resourceFinder = resourceFinder;
        this.postConstruct();
    }

    protected IClass findIClass(String descriptor) throws ClassNotFoundException {

        String className = Descriptor.toClassName(descriptor);

        String classFileResourceName = ClassFile.getClassFileResourceName(className);
        
        // Find the class file resource.
        Resource classFileResource = this.resourceFinder.findResource(classFileResourceName);

        if (classFileResource == null) {
            return null;
        }

        // Open the class file resource.
        InputStream is;

        try {
            is = classFileResource.open();
        } catch (IOException ex) {
            throw new ClassNotFoundException("Opening resource \"" + classFileResource.getFileName() + "\"");
        }

        // Load the IClass from the class file.
        ClassFile cf;

        try {
            cf = new ClassFile(is);
        } catch (IOException e) {
            throw new ClassNotFoundException("Reading resource \"" + classFileResource.getFileName() + "\"");
        } finally {
            try {
                is.close();
            } catch (IOException e) {
            }
        }

        IClass iClass = new ClassFileIClass(cf, this);
        this.defineIClass(iClass);
        return iClass;
    }
}
